package com.hfi.ood.litejunit.v2.framework.runner;

import com.hfi.ood.litejunit.v2.framework.Test;
import com.hfi.ood.litejunit.v2.framework.TestSuite;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.NumberFormat;

/**
 * @author ChangLiang
 * @date 2020/5/26
 */
public abstract class BaseTestRunner implements TestListener {

    public static final String SUITE_METHOD_NAME = "suite";

    public static String getFilteredTrace(Throwable throwable) {
        StringWriter stringWriter = new StringWriter();
        PrintWriter writer = new PrintWriter(stringWriter);
        throwable.printStackTrace(writer);
        StringBuffer buffer = stringWriter.getBuffer();
        return buffer.toString();
    }

    /**
     * 通过反射 从xxxTestSuite 约定的static Test suite()方法中 生成Test
     * @param suiteClassName
     * @return
     */
    public Test getTest(String suiteClassName) {
        if (suiteClassName.length() <= 0) {
            return null;
        }

        Class testClass = null;
        try {
            testClass = this.loadSuiteClass(suiteClassName);
        } catch (ClassNotFoundException e) {
            String clazz = e.getMessage();
            if (clazz == null) {
                clazz = suiteClassName;
            }
            runFailed("Class not found \"" + clazz + "\"");
            return null;
        } catch (Exception e) {
            runFailed("Error: " + e.toString());
            return null;
        }

        Method suiteMethod = null;
        try {
            suiteMethod = testClass.getMethod(SUITE_METHOD_NAME, new Class[0]);
        } catch (Exception e) {
            // try to extract a test suite automatically clearStatus();
            return new TestSuite(testClass);
        }

        Test test = null;
        try {
            // static method
            test = (Test) suiteMethod.invoke(null, new Class[0]);
            if (test == null) {
                return test;
            }
        } catch (IllegalAccessException e) {
            runFailed("Failed to invoke suite():" + e.toString());
            return null;
        } catch (InvocationTargetException e) {
            runFailed("Failed to invoke suite():" + e.getTargetException().toString());
            return null;
        }
        // clearStatus();
        return test;
    }

    private Class<?> loadSuiteClass(String suiteClassName) throws ClassNotFoundException {
        return Class.forName(suiteClassName);
    }

    public abstract void runFailed(String message);

    /**
     * 转换为秒
     * @param runTime
     * @return
     */
    public String elapsedTimeAsString(long runTime) {
        return NumberFormat.getInstance().format(runTime / 1000);
    }
}
